package org.eiahe.hr.salary.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ehe.common.core.utils.MapstructUtils;
import org.ehe.common.core.utils.StringUtils;
import org.ehe.common.excel.core.ExcelResult;
import org.ehe.common.excel.utils.ExcelUtil;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.system.domain.bo.HrEmployeeBo;
import org.ehe.system.domain.vo.HrEmployeeVo;
import org.ehe.system.domain.vo.SysDeptVo;
import org.ehe.system.domain.vo.SysUserVo;
import org.ehe.system.service.IHrEmployeeService;
import org.ehe.system.service.ISysDeptService;
import org.ehe.system.service.ISysUserService;
import org.eiahe.hr.salary.domain.SalaryImportRecord;
import org.eiahe.hr.salary.domain.SalaryStructure;
import org.eiahe.hr.salary.domain.bo.SalaryImportRecordBo;
import org.eiahe.hr.salary.domain.vo.SalaryImportVo;
import org.eiahe.hr.salary.domain.vo.SalaryImportRecordVo;
import org.eiahe.hr.salary.mapper.SalaryImportRecordMapper;
import org.eiahe.hr.salary.mapper.SalaryStructureMapper;
import org.eiahe.hr.salary.service.ISalaryImportRecordService;
import org.eiahe.hr.salary.util.SalaryExcelParser;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.*;

/**
 * 薪资导入记录Service业务层处理
 *
 * @author zhangnn
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SalaryImportRecordServiceImpl implements ISalaryImportRecordService {

    private final SalaryImportRecordMapper importRecordMapper;
    private final SalaryStructureMapper salaryStructureMapper;
    private final IHrEmployeeService employeeService;
    private final ISysUserService userService;
    private final ISysDeptService deptService;

    @Override
    public SalaryImportRecordVo queryById(Long recordId) {
        SalaryImportRecordVo vo = importRecordMapper.selectVoById(recordId);
        return vo;
    }

    @Override
    public List<SalaryImportRecordVo> queryList(SalaryImportRecordBo bo) {
        LambdaQueryWrapper<SalaryImportRecord> lqw = buildQueryWrapper(bo);
        List<SalaryImportRecordVo> salaryImportRecordVos = importRecordMapper.selectVoList(lqw);
        salaryImportRecordVos.forEach(p -> {
            Long createBy = p.getCreateBy();
            SysUserVo sysUserVo = userService.selectUserById(Long.valueOf(createBy));
            if (Objects.nonNull(sysUserVo)) {
                p.setCreateName(sysUserVo.getNickName());
            }
        });
        return salaryImportRecordVos;
    }

    @Override
    public TableDataInfo<SalaryImportRecordVo> queryPageList(SalaryImportRecordBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<SalaryImportRecord> lqw = buildQueryWrapper(bo);
        IPage<SalaryImportRecordVo> page = importRecordMapper.selectVoPage(pageQuery.build(), lqw);
        page.getRecords().forEach(p -> {
            Long createBy = p.getCreateBy();
            SysUserVo sysUserVo = userService.selectUserById(Long.valueOf(createBy));
            if (Objects.nonNull(sysUserVo)) {
                p.setCreateName(sysUserVo.getNickName());
            }
        });
        return TableDataInfo.build(page);
    }

    /**
     * 构建查询条件
     *
     * @param bo 薪资导入记录业务对象
     * @return 查询条件
     */
    private LambdaQueryWrapper<SalaryImportRecord> buildQueryWrapper(SalaryImportRecordBo bo) {
        LambdaQueryWrapper<SalaryImportRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getEmployeeNo()), SalaryImportRecord::getEmployeeNo, bo.getEmployeeNo());
        lqw.eq(StringUtils.isNotBlank(bo.getEmployeeName()), SalaryImportRecord::getEmployeeName, bo.getEmployeeName());
        lqw.eq(StringUtils.isNotBlank(bo.getYearMonth()), SalaryImportRecord::getYearMonth, bo.getYearMonth());
        lqw.eq(StringUtils.isNotBlank(bo.getFileName()), SalaryImportRecord::getFileName, bo.getFileName());
        lqw.eq(StringUtils.isNotBlank(bo.getImportStatus()), SalaryImportRecord::getImportStatus, bo.getImportStatus());
        lqw.orderByDesc(SalaryImportRecord::getCreateTime);
        return lqw;
    }

    @Override
    public Boolean insertByBo(SalaryImportRecordBo bo) {
        SalaryImportRecord add = MapstructUtils.convert(bo, SalaryImportRecord.class);
        validEntityBeforeSave(add);
        boolean flag = importRecordMapper.insert(add) > 0;
        if (flag) {
            bo.setRecordId(add.getRecordId());
        }
        return flag;
    }

    @Override
    public Boolean updateByBo(SalaryImportRecordBo bo) {
        SalaryImportRecord update = MapstructUtils.convert(bo, SalaryImportRecord.class);
        validEntityBeforeSave(update);
        return importRecordMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(SalaryImportRecord entity) {
        // TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        return importRecordMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 导入薪资数据
     *
     * @param file      Excel文件
     * @param yearMonth 年月
     * @return 导入记录ID
     */
    @Override
    public Long importSalaryData(MultipartFile file, String yearMonth) {
        try {
            log.info("开始导入薪资数据，文件名: {}, 年月: {}", file.getOriginalFilename(), yearMonth);
            if (yearMonth.contains(",")) {
                yearMonth = yearMonth.replace(",", "");
            }
            // 验证文件格式
            String fileName = file.getOriginalFilename();
            if (fileName == null || (!fileName.endsWith(".xlsx") && !fileName.endsWith(".xls"))) {
                throw new IllegalArgumentException("请上传Excel文件(.xlsx或.xls格式)");
            }

            // 验证年月格式
            if (yearMonth == null || yearMonth.length() != 6 || !yearMonth.matches("\\d{6}")) {
                throw new IllegalArgumentException("年月格式不正确，请使用yyyyMM格式");
            }

            // 1. 创建导入记录
            SalaryImportRecord record = new SalaryImportRecord();
            record.setFileName(fileName);
            record.setYearMonth(yearMonth);
            record.setImportStatus("1"); // 处理中
            record.setTotalRecords(0);
            record.setSuccessRecords(0);
            record.setFailedRecords(0);
            importRecordMapper.insert(record);

            // 2. 解析Excel文件
            List<SalaryImportVo> dataList;
            List<String> errorList = new ArrayList<>();
            try {
                dataList = SalaryExcelParser.parseSalaryExcel(file.getInputStream());
                log.info("Excel解析完成，总记录数: {}", dataList.size());

                // 打印前几条数据用于调试
                if (!dataList.isEmpty()) {
                    log.info("第一条数据: {}", dataList.get(0));
                }
            } catch (Exception e) {
                log.error("Excel解析异常: ", e);
                throw new IllegalArgumentException("Excel文件格式不正确，请检查文件内容和格式，错误信息: " + e.getMessage());
            }

            log.info("解析Excel文件完成，总记录数: {}, 错误记录数: {}", dataList.size(), errorList.size());

            // 3. 更新导入记录统计信息
            record.setTotalRecords(dataList.size());
            record.setFailedRecords(errorList.size());

            // 4. 导入数据到薪资结构表
            int successCount = 0;
            List<SalaryStructure> importedStructures = new ArrayList<>(); // 记录已导入的数据，用于回滚
            for (SalaryImportVo importVo : dataList) {
                try {
                    // 验证必要字段
                    if (StringUtils.isBlank(importVo.getEmployeeNo())) {
                        errorList.add("第" + (successCount + 1) + "行数据工号不能为空");
                        continue;
                    }

                    if (StringUtils.isBlank(importVo.getEmployeeName())) {
                        errorList.add("第" + (successCount + 1) + "行数据员工姓名不能为空");
                        continue;
                    }

                    SalaryStructure salaryStructure = MapstructUtils.convert(importVo, SalaryStructure.class);
                    salaryStructure.setYearMonth(yearMonth);
                    salaryStructure.setDataSource("1"); // 导入
                    // 设置其他必要字段
                    salaryStructure.setStatus("0"); // 正常状态

                    // 自动计算缺失的薪资字段
                    calculateMissingSalaryFields(salaryStructure);

                    String employeeName = salaryStructure.getEmployeeName();
                    if (StringUtils.isNotBlank(employeeName)) {
                        HrEmployeeBo bo = new HrEmployeeBo();
                        bo.setEmployeeName(employeeName);
                        List<HrEmployeeVo> hrEmployeeVos = employeeService.queryList(bo);
                        if (CollUtil.isNotEmpty(hrEmployeeVos)) {
                            String employeeNo = hrEmployeeVos.get(0).getEmployeeNo();
                            salaryStructure.setEmployeeNo(employeeNo);
                        }
                    }

                    // 检查是否已存在该员工该月的数据，如果存在则更新，否则新增
                    LambdaQueryWrapper<SalaryStructure> queryWrapper = Wrappers.lambdaQuery();
                    queryWrapper.eq(SalaryStructure::getEmployeeNo, importVo.getEmployeeNo());
                    queryWrapper.eq(SalaryStructure::getYearMonth, yearMonth);

                    SalaryStructure existing = salaryStructureMapper.selectOne(queryWrapper);
                    if (existing != null) {
                        salaryStructure.setStructureId(existing.getStructureId());
                        salaryStructureMapper.updateById(salaryStructure);
                        log.debug("更新员工{}的薪资数据", importVo.getEmployeeNo());
                    } else {
                        salaryStructureMapper.insert(salaryStructure);
                        log.debug("新增员工{}的薪资数据", importVo.getEmployeeNo());
                        // 记录新增的数据，用于回滚
                        importedStructures.add(salaryStructure);
                    }
                    successCount++;
                } catch (Exception e) {
                    // 记录错误但继续处理其他数据
                    String errorMsg = "员工" + importVo.getEmployeeNo() + "数据导入失败: " + e.getMessage();
                    log.error(errorMsg, e);
                    errorList.add(errorMsg);
                }
            }

            // 5. 更新导入记录最终状态
            record.setSuccessRecords(successCount);
            record.setFailedRecords(errorList.size());
            record.setImportStatus(successCount > 0 ? "2" : "3"); // 成功或失败
            if (!errorList.isEmpty()) {
                record.setErrorMessage(String.join("; ", errorList));
            }
            importRecordMapper.updateById(record);

            log.info("薪资数据导入完成，成功记录数: {}, 失败记录数: {}", successCount, errorList.size());
            return record.getRecordId();
        } catch (Exception e) {
            log.error("薪资数据导入失败", e);
            // 记录导入失败
            SalaryImportRecord record = new SalaryImportRecord();
            record.setFileName(file.getOriginalFilename());
            record.setYearMonth(yearMonth);
            record.setImportStatus("3"); // 失败
            record.setErrorMessage(e.getMessage());
            importRecordMapper.insert(record);
            return record.getRecordId();
        }
    }

    /**
     * 回滚导入的数据
     *
     * @param recordId 导入记录ID
     * @return 是否回滚成功
     */
    @Override
    public Boolean rollbackImport(Long recordId) {
        try {
            // 查询导入记录
            SalaryImportRecord record = importRecordMapper.selectById(recordId);
            if (record == null) {
                return false;
            }

            // 检查导入状态，只有成功的导入才能回滚
            if (!"2".equals(record.getImportStatus())) {
                return false;
            }

            // 查询该次导入的所有薪资数据
            LambdaQueryWrapper<SalaryStructure> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(SalaryStructure::getYearMonth, record.getYearMonth());

            List<SalaryStructure> structures = salaryStructureMapper.selectList(queryWrapper);

            // 删除该次导入的数据
            for (SalaryStructure structure : structures) {
                salaryStructureMapper.deleteById(structure.getStructureId());
            }

            // 更新导入记录状态为已回滚
            record.setImportStatus("4"); // 已回滚
            importRecordMapper.updateById(record);

            return true;
        } catch (Exception e) {
            log.error("回滚导入数据失败", e);
            return false;
        }
    }

    /**
     * 重试导入失败的记录
     *
     * @param recordId 导入记录ID
     * @return 是否重试成功
     */
    @Override
    public Boolean retryImport(Long recordId) {
        try {
            // 查询导入记录
            SalaryImportRecord record = importRecordMapper.selectById(recordId);
            if (record == null) {
                return false;
            }

            // 检查导入状态，只有失败的导入才能重试
            if (!"3".equals(record.getImportStatus())) {
                return false;
            }

            // TODO: 这里需要重新获取原始文件并重新导入
            // 由于文件可能已不存在，实际实现中需要将原始文件保存到文件系统或数据库中
            log.warn("重试导入功能需要保存原始文件，当前仅记录日志");

            // 更新导入记录状态为重试中
            record.setImportStatus("1"); // 处理中
            importRecordMapper.updateById(record);

            return true;
        } catch (Exception e) {
            log.error("重试导入数据失败", e);
            return false;
        }
    }

    /**
     * 自动计算薪资结构中缺失的字段
     *
     * @param salaryStructure 薪资结构实体
     */
    private void calculateMissingSalaryFields(SalaryStructure salaryStructure) {
        // 自动计算应发工资（如果没有提供的话）
        if (salaryStructure.getGrossSalary() == null) {
            BigDecimal calculatedGross = BigDecimal.ZERO;
            if (salaryStructure.getBaseSalary() != null)
                calculatedGross = calculatedGross.add(salaryStructure.getBaseSalary());
            if (salaryStructure.getPerformanceSalary() != null)
                calculatedGross = calculatedGross.add(salaryStructure.getPerformanceSalary());
            if (salaryStructure.getDutyAllowance() != null)
                calculatedGross = calculatedGross.add(salaryStructure.getDutyAllowance());
            if (salaryStructure.getMealAllowance() != null)
                calculatedGross = calculatedGross.add(salaryStructure.getMealAllowance());
            if (salaryStructure.getOtherAdjustment() != null)
                calculatedGross = calculatedGross.add(salaryStructure.getOtherAdjustment());
            if (salaryStructure.getAbsenceDeduction() != null)
                calculatedGross = calculatedGross.subtract(salaryStructure.getAbsenceDeduction());
            if (salaryStructure.getMealDeduction() != null)
                calculatedGross = calculatedGross.subtract(salaryStructure.getMealDeduction());
            salaryStructure.setGrossSalary(calculatedGross);
        }

        // 自动计算社保公积金合计（如果没有提供的话）
        if (salaryStructure.getSocialHousingTotal() == null) {
            BigDecimal calculatedSocialHousing = BigDecimal.ZERO;
            if (salaryStructure.getPensionDeduction() != null)
                calculatedSocialHousing = calculatedSocialHousing.add(salaryStructure.getPensionDeduction());
            if (salaryStructure.getUnemploymentDeduction() != null)
                calculatedSocialHousing = calculatedSocialHousing.add(salaryStructure.getUnemploymentDeduction());
            if (salaryStructure.getMedicalDeduction() != null)
                calculatedSocialHousing = calculatedSocialHousing.add(salaryStructure.getMedicalDeduction());
            if (salaryStructure.getMajorMedicalDeduction() != null)
                calculatedSocialHousing = calculatedSocialHousing.add(salaryStructure.getMajorMedicalDeduction());
            if (salaryStructure.getHousingFundPersonal() != null)
                calculatedSocialHousing = calculatedSocialHousing.add(salaryStructure.getHousingFundPersonal());
            salaryStructure.setSocialHousingTotal(calculatedSocialHousing);
        }

        // 自动计算税前工资（如果没有提供的话）
        if (salaryStructure.getTaxableSalary() == null) {
            BigDecimal taxableSalary = salaryStructure.getGrossSalary() != null ? salaryStructure.getGrossSalary()
                    : BigDecimal.ZERO;
            if (salaryStructure.getSocialHousingTotal() != null) {
                taxableSalary = taxableSalary.subtract(salaryStructure.getSocialHousingTotal());
            }
            salaryStructure.setTaxableSalary(taxableSalary);
        }

        // 注意：个人所得税和实发工资需要根据具体税率计算，这里暂不自动计算个人所得税
        // 实发工资 = 税前工资 - 个人所得税，如果未提供个人所得税，则实发工资 = 税前工资
        if (salaryStructure.getNetSalary() == null) {
            BigDecimal netSalary = salaryStructure.getTaxableSalary() != null ? salaryStructure.getTaxableSalary()
                    : BigDecimal.ZERO;
            if (salaryStructure.getPersonalTax() != null) {
                netSalary = netSalary.subtract(salaryStructure.getPersonalTax());
            }
            salaryStructure.setNetSalary(netSalary);
        }
    }
}
